//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_recycle_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_issue_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_recycle_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectRecycleApiImpl) Clear(ctx context.Context, req *project_recycle_api.ClearRequest) (*project_recycle_api.ClearResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_recycle_api.ClearResponse{
			Code:   project_recycle_api.ClearResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_recycle_api.ClearResponse{
			Code:   project_recycle_api.ClearResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_recycle_api.ClearResponse{
			Code:   project_recycle_api.ClearResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_recycle_api.ClearResponse{
			Code:   project_recycle_api.ClearResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_recycle_api.ClearResponse{
			Code:   project_recycle_api.ClearResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	itemTypeList := []uint32{}
	for _, recycleItemType := range req.RecycleItemTypeList {
		itemTypeList = append(itemTypeList, uint32(recycleItemType))
	}

	recycleItemList, err := project_dao.RecycleDao.ListByType(ctx, req.ProjectId, itemTypeList)
	if err != nil {
		return nil, err
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		for _, recycleItem := range recycleItemList {
			err = project_dao.RecycleDao.Remove(sessCtx, req.ProjectId, recycleItem.RecycleItemId)
			if err != nil {
				return nil, err
			}
			if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_IDEA) {
				err = apiImpl.removeIdea(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_REQUIREMENT) {
				err = apiImpl.removeRequirement(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_TASK) {
				err = apiImpl.removeIssue(sessCtx, projectItem, recycleItem.RecycleItemId, project_issue_api.ISSUE_TYPE_ISSUE_TYPE_TASK)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_BUG) {
				err = apiImpl.removeIssue(sessCtx, projectItem, recycleItem.RecycleItemId, project_issue_api.ISSUE_TYPE_ISSUE_TYPE_BUG)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_TESTCASE) {
				err = apiImpl.removeTestcase(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_BULLETIN) {
				err = apiImpl.removeBulletin(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_SPRIT) {
				err = apiImpl.removeSprit(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_DOC) {
				err = apiImpl.removeDoc(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_PAGES) {
				err = apiImpl.removePages(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_BOARD) {
				err = apiImpl.removeBoard(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_FILE) {
				err = apiImpl.removeFile(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			} else if recycleItem.RecycleItemType == uint32(project_recycle_api.RECYCLE_ITEM_TYPE_RECYCLE_ITEM_API_COLL) {
				err = apiImpl.removeApiColl(sessCtx, projectItem, recycleItem.RecycleItemId)
				if err != nil {
					return nil, err
				}
			}
		}
		return &project_recycle_api.ClearResponse{
			Code: project_recycle_api.ClearResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//记录事件
	go apiImpl.addClearFromRecycleEvent(sessionItem, projectItem, itemTypeList, time.Now().UnixNano()/1e6)
	return ret.(*project_recycle_api.ClearResponse), nil
}
